//
// Created by Jisam on 2024/8/17 21:26.
// Solution of  d
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <vector>

using namespace std;

#define endl "\n"
#define PSI pair<string,int>
#define PII pair<int,int>
#define PDI pair<double,int>
#define PDD pair<double,double>
#define VVI vector<vector<int>>
#define VI vector<int>
#define VS vector<string>

#define PQLI priority_queue<int, vector<int>, less<int>>
#define PQGI priority_queue<int, vector<int>, greater<int>>
#define code_by_jisam ios::sync_with_stdio(false),cin.tie(nullptr)
using namespace std;
using ll = long long;
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;

constexpr i64 INF = 2e18;

int f(i64 x) {
    return x == 0 ? ((x - 1) % 9  + 1 ): 0;
}

#define ls u << 1
#define rs u << 1 | 1

template<class Info>
struct SegmentTree {
    int n;
    vector<Info> tr;

    SegmentTree(int _) : n(_), tr(_ << 2) {}

    SegmentTree(vector<i64> a) : SegmentTree(int(a.size() - 1)) {
        function<void(int, int, int)> build = [&](int u, int l, int r) -> void {
            if (l == r) {
                tr[u] = {l, r, 1, a[l], a[l], a[l]};
                return;
            }
            tr[u] = {l, r};
            int mid = (l + r) >> 1;
            build(ls, l, mid), build(rs, mid + 1, r);
            pushup(u);
        };
        build(1, 1, n);
    }

    void apply(int u, int v) {
        tr[u].apply(v);
    }

    void pushup(int u) {
        tr[u] = tr[ls] + tr[rs];
    }

    void modify(int u, int l, int r) {
        if (tr[u].l == tr[u].r) {
            apply(u, 0);
            return;
        }
        if (l <= tr[u].l && tr[u].r <= r && tr[u].max < 10) return;
        int mid = (tr[u].l + tr[u].r) >> 1;
        if (l <= mid) {
            modify(ls, l, r);
        }
        if (r > mid) {
            modify(rs, l, r);
        }
        pushup(u);
    }

    Info query(int u, int l, int r) {
        if (l <= tr[u].l && tr[u].r <= r) {
            return tr[u];
        }
        if (r <= tr[ls].r) {
            return query(ls, l, r);
        } else if (l >= tr[rs].l) {
            return query(rs, l, r);
        } else {
            return query(ls, l, r) + query(rs, l, r);
        }
    }
};


struct Info {
    int l, r, cnt;
    i64 min, max, v;

    void apply(int x) {
        v = f(v);
        min = max = v;
    }
};

Info operator+(Info a, Info b) {
    Info res{};
    res.l = a.l;
    res.r = b.r;
    res.cnt = a.cnt + b.cnt;
    res.min = min(a.min, b.min);
    res.max = max(a.max, b.max);
    return res;
}

int main() {
    code_by_jisam;
    int n;
    cin >> n;
    vector<i64> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    SegmentTree<Info> seg(a);
    int m;
    cin >> m;
    while (m--) {
        int op, l, r;
        cin >> op >> l >> r;
        if (op == 1) {
            seg.modify(1, l, r);
        } else {
            cout << seg.query(1, l, r).min << '\n';
        }
    }

    return 0;
}